package math2.delaunay;

import static java.lang.Math.abs;
import static java.lang.Math.acos;

public class Triangle {

	private static final double EPS = 1e-13;

	private Point ccc;
	private Point pi;
	private Point pj;
	private Point pk;
	private double r;

	public Triangle(Point pi, Point pj, Point pk) {
		Point dij = pi.add(-1, pj);
		Point djk = pj.add(-1, pk);
		double dxij = dij.getX();
		double dyij = dij.getY();
		double dxjk = djk.getX();
		double dyjk = djk.getY();
		double li2 = pi.scalarProduct(pi);
		double lj2 = pj.scalarProduct(pj);
		double lk2 = pk.scalarProduct(pk);
		double d = 2 * (dxij * dyjk - dxjk * dyij);
		double dx = (li2 - lj2) * dyjk - (lj2 - lk2) * dyij;
		double dy = (lj2 - lk2) * dxij - (li2 - lj2) * dxjk;

		this.pi = pi;
		this.pj = pj;
		this.pk = pk;
		this.ccc = new Point(dx / d, dy / d);
		this.r = this.pi.distanceTo(this.ccc);
	}

	private double angle(Point p1, Point p2, Point p3) {
		Point d1 = p2.add(-1, p1);
		Point d2 = p3.add(-1, p1);
		return abs(acos(d1.scalarProduct(d2) / (d1.norm2() * d2.norm2())));
	}

	public double getAngle(int idx) {
		if (idx == 0) {
			return angle(this.pi, this.pj, this.pk);
		}
		if (idx == 1) {
			return angle(this.pj, this.pk, this.pi);
		}
		return angle(this.pk, this.pi, this.pj);
	}

	public Point getCCC() {
		return this.ccc;
	}

	public Edge[] getEdges() {
		return new Edge[] { new Edge(this.pi, this.pj),
				new Edge(this.pj, this.pk), new Edge(this.pk, this.pi) };
	}

	public Point getPi() {
		return this.pi;
	}

	public Point getPj() {
		return this.pj;
	}

	public Point getPk() {
		return this.pk;
	}

	public Point[] getPoints() {
		return new Point[] { this.pi, this.pj, this.pk };
	}

	public boolean hasPoint(Point p) {
		return p == this.pi || p == this.pj || p == this.pk;
	}

	public boolean isInsideCCM(Point p) {
		return this.ccc.distanceTo(p) <= this.r - EPS;
	}

	public boolean isInsideCCP(Point p) {
		return this.ccc.distanceTo(p) <= this.r + EPS;
	}
}
